<template>
	<view class="mask flex-center">
		<view class="content botton-radius">
			<view class="content-top">
				<text class="content-top-text">{{ title }}</text>
				<image
					src="../images/bg_top.png"
					class="content-top"
					style="top: 0"
					height="100%"
					width="100%"
				>
				</image>
			</view>
			<view class="content-header"></view>
			<view class="content-body">
				<view class="title">{{ subTitle }}</view>
				<view class="body">
					<scroll-view class="box-des-scroll" scroll-y="true">
						<text class="box-des">{{ contents }}</text>
					</scroll-view>
				</view>
				<view class="footer flex-center">
					<template v-if="isAppStore">
						<button
							style="border: none; color: #fff"
							class="content-button"
							plain
							@click="jumpToAppStore"
						>
							{{ downLoadBtnTextiOS }}
						</button>
					</template>
					<template v-else>
						<template v-if="!downloadSuccess">
							<view class="progress-box flex-column" v-if="downloading">
								<progress
									activeColor="#3DA7FF"
									border-radius="35"
									stroke-width="10"
									class="progress"
									show-info
									:percent="downLoadPercent"
								></progress>
								<view
									style="
										width: 100%;
										display: flex;
										font-size: 28rpx;
										justify-content: space-around;
									"
								>
									<text>{{ downLoadingText }}</text>
									<text>({{ downloadedSize }}/{{ packageFileSize }}M)</text>
								</view>
							</view>
							<button
								v-else
								style="border: none; color: #fff"
								class="content-button"
								plain
								@click="updateApp"
							>
								{{ downLoadBtnText }}
							</button>
						</template>
						<button
							v-else-if="downloadSuccess && !installed"
							style="border: none; color: #fff"
							class="content-button"
							plain
							:loading="installing"
							:disabled="installing"
							@click="installPackage"
						>
							{{ installing ? "正在安装……" : "下载完成，立即安装" }}
						</button>
						<button
							style="border: none; color: #fff"
							v-if="installed && isWGT"
							class="content-button"
							plain
							@click="restart"
						>
							安装完毕，点击重启
						</button>
					</template>
				</view>
			</view>
			<image
				src="../images/app_update_close.png"
				v-if="!is_mandatory"
				class="close-img"
				@click.stop="closeUpdate"
			></image>
		</view>
	</view>
</template>

<script>
const localFilePathKey = "UNI_ADMIN_UPGRADE_CENTER_LOCAL_FILE_PATH"
const platform_iOS = "iOS"
let downloadTask = null
let openSchemePromise

/**
 * 对比版本号，如需要，请自行修改判断规则
 * 支持比对	("3.0.0.0.0.1.0.1", "3.0.0.0.0.1")	("3.0.0.1", "3.0")	("3.1.1", "3.1.1.1") 之类的
 * @param {Object} v1
 * @param {Object} v2
 * v1 > v2 return 1
 * v1 < v2 return -1
 * v1 == v2 return 0
 */
function compare(v1 = "0", v2 = "0") {
	v1 = String(v1).split(".")
	v2 = String(v2).split(".")
	const minVersionLens = Math.min(v1.length, v2.length)

	let result = 0
	for (let i = 0; i < minVersionLens; i++) {
		const curV1 = Number(v1[i])
		const curV2 = Number(v2[i])

		if (curV1 > curV2) {
			result = 1
			break
		} else if (curV1 < curV2) {
			result = -1
			break
		}
	}

	if (result === 0 && v1.length !== v2.length) {
		const v1BiggerThenv2 = v1.length > v2.length
		const maxLensVersion = v1BiggerThenv2 ? v1 : v2
		for (let i = minVersionLens; i < maxLensVersion.length; i++) {
			const curVersion = Number(maxLensVersion[i])
			if (curVersion > 0) {
				v1BiggerThenv2 ? (result = 1) : (result = -1)
				break
			}
		}
	}

	return result
}

export default {
	data() {
		return {
			// 从之前下载安装
			installForBeforeFilePath: "",

			// 安装
			installed: false,
			installing: false,

			// 下载
			downloadSuccess: false,
			downloading: false,

			downLoadPercent: 0,
			downloadedSize: 0,
			packageFileSize: 0,

			tempFilePath: "", // 要安装的本地包地址

			// 默认安装包信息
			title: "更新日志",
			contents: "",
			is_mandatory: false,

			// 可自定义属性
			subTitle: "发现新版本",
			downLoadBtnTextiOS: "立即跳转更新",
			downLoadBtnText: "立即下载更新",
			downLoadingText: "安装包下载中，请稍后"
		}
	},
	onLoad({ local_storage_key }) {
		if (!local_storage_key) {
			console.error("local_storage_key为空，请检查后重试")
			uni.navigateBack()
			return
		}

		const localPackageInfo = uni.getStorageSync(local_storage_key)
		if (!localPackageInfo) {
			console.error("安装包信息为空，请检查后重试")
			uni.navigateBack()
			return
		}

		const requiredKey = ["version", "url", "type"]
		for (let key in localPackageInfo) {
			if (requiredKey.indexOf(key) !== -1 && !localPackageInfo[key]) {
				console.error(`参数 ${key} 必填，请检查后重试`)
				uni.navigateBack()
				return
			}
		}

		Object.assign(this, localPackageInfo)
		this.checkLocalStoragePackage()
	},
	onBackPress() {
		// 强制更新不允许返回
		if (this.is_mandatory) {
			return true
		}

		downloadTask && downloadTask.abort()
	},
	onHide() {
		openSchemePromise = null
	},
	computed: {
		isWGT() {
			return this.type === "wgt"
		},
		isiOS() {
			return !this.isWGT && this.platform ? this.platform.includes(platform_iOS) : false
		},
		isAppStore() {
			return this.isiOS || (!this.isiOS && !this.isWGT && this.url.indexOf(".apk") === -1)
		}
	},
	methods: {
		checkLocalStoragePackage() {
			// 如果已经有下载好的包，则直接提示安装
			const localFilePathRecord = uni.getStorageSync(localFilePathKey)
			if (localFilePathRecord) {
				const { version, savedFilePath, installed } = localFilePathRecord

				// 比对版本
				if (!installed && compare(version, this.version) === 0) {
					this.downloadSuccess = true
					this.installForBeforeFilePath = savedFilePath
					this.tempFilePath = savedFilePath
				} else {
					// 如果保存的包版本小 或 已安装过，则直接删除
					this.deleteSavedFile(savedFilePath)
				}
			}
		},
		async closeUpdate() {
			if (this.downloading) {
				if (this.is_mandatory) {
					return uni.showToast({ title: "下载中，请稍后……", icon: "none", duration: 500 })
				}
				uni.showModal({
					title: "是否取消下载？",
					cancelText: "否",
					confirmText: "是",
					success: res => {
						if (res.confirm) {
							downloadTask && downloadTask.abort()
							uni.navigateBack()
						}
					}
				})
				return
			}

			if (this.downloadSuccess && this.tempFilePath) {
				// 包已经下载完毕，稍后安装，将包保存在本地
				await this.saveFile(this.tempFilePath, this.version)
				uni.navigateBack()
				return
			}

			uni.navigateBack()
		},
		updateApp() {
			this.checkStoreScheme().catch(() => {
				this.downloadPackage()
			})
		},
		// 跳转应用商店
		checkStoreScheme() {
			const storeList = (this.store_list || []).filter(item => item.enable)
			if (storeList && storeList.length) {
				storeList
					.sort((cur, next) => next.priority - cur.priority)
					.map(item => item.scheme)
					.reduce((promise, cur, curIndex) => {
						openSchemePromise = (promise || (promise = Promise.reject())).catch(() => {
							return new Promise((resolve, reject) => {
								plus.runtime.openURL(cur, err => {
									reject(err)
								})
							})
						})
						return openSchemePromise
					}, openSchemePromise)
				return openSchemePromise
			}

			return Promise.reject()
		},
		downloadPackage() {
			this.downloading = true

			//下载包
			downloadTask = uni.downloadFile({
				url: this.url,
				success: res => {
					if (res.statusCode == 200) {
						this.downloadSuccess = true
						this.tempFilePath = res.tempFilePath

						// 强制更新，直接安装
						if (this.is_mandatory) {
							this.installPackage()
						}
					}
				},
				complete: () => {
					this.downloading = false

					this.downLoadPercent = 0
					this.downloadedSize = 0
					this.packageFileSize = 0

					downloadTask = null
				}
			})

			downloadTask.onProgressUpdate(res => {
				this.downLoadPercent = res.progress
				this.downloadedSize = (res.totalBytesWritten / Math.pow(1024, 2)).toFixed(2)
				this.packageFileSize = (
					res.totalBytesExpectedToWrite / Math.pow(1024, 2)
				).toFixed(2)
			})
		},
		installPackage() {
			// #ifdef APP-PLUS
			// wgt资源包安装
			if (this.isWGT) {
				this.installing = true
			}
			plus.runtime.install(
				this.tempFilePath,
				{
					force: false
				},
				async res => {
					this.installing = false
					this.installed = true

					// wgt包，安装后会提示 安装成功，是否重启
					if (this.isWGT) {
						// 强制更新安装完成重启
						if (this.is_mandatory) {
							uni.showLoading({ icon: "none", title: "安装成功，正在重启……" })

							setTimeout(() => {
								uni.hideLoading()
								this.restart()
							}, 1000)
						}
					} else {
						const localFilePathRecord = uni.getStorageSync(localFilePathKey)
						uni.setStorageSync(localFilePathKey, {
							...localFilePathRecord,
							installed: true
						})
					}
				},
				async err => {
					// 如果是安装之前的包，安装失败后删除之前的包
					if (this.installForBeforeFilePath) {
						await this.deleteSavedFile(this.installForBeforeFilePath)
						this.installForBeforeFilePath = ""
					}

					// 安装失败需要重新下载安装包
					this.installing = false
					this.installed = false

					uni.showModal({
						title: "更新失败，请重新下载",
						content: err.message,
						showCancel: false
					})
				}
			)

			// 非wgt包，安装跳出覆盖安装，此处直接返回上一页
			if (!this.isWGT && !this.is_mandatory) {
				uni.navigateBack()
			}
			// #endif
		},
		restart() {
			this.installed = false
			// #ifdef APP-PLUS
			//更新完重启app
			plus.runtime.restart()
			// #endif
		},
		saveFile(tempFilePath, version) {
			return new Promise((resolve, reject) => {
				uni.saveFile({
					tempFilePath,
					success({ savedFilePath }) {
						uni.setStorageSync(localFilePathKey, { version, savedFilePath })
					},
					complete() {
						resolve()
					}
				})
			})
		},
		deleteSavedFile(filePath) {
			uni.removeStorageSync(localFilePathKey)
			return uni.removeSavedFile({
				filePath
			})
		},
		jumpToAppStore() {
			plus.runtime.openURL(this.url)
		}
	}
}
</script>

<style>
page {
	background: transparent;
}

.flex-center {
	/* #ifndef APP-NVUE */
	display: flex;
	/* #endif */
	justify-content: center;
	align-items: center;
}

.mask {
	position: fixed;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	background-color: rgba(0, 0, 0, 0.65);
}

.botton-radius {
	border-bottom-left-radius: 30rpx;
	border-bottom-right-radius: 30rpx;
}

.content {
	position: relative;
	top: 0;
	width: 600rpx;
	background-color: #fff;
	box-sizing: border-box;
	padding: 0 50rpx;
	font-family: Source Han Sans CN;
}

.text {
	/* #ifndef APP-NVUE */
	display: block;
	/* #endif */
	line-height: 200px;
	text-align: center;
	color: #ffffff;
}

.content-top {
	position: absolute;
	top: -195rpx;
	left: 0;
	width: 600rpx;
	height: 270rpx;
}

.content-top-text {
	font-size: 45rpx;
	font-weight: bold;
	color: #f8f8fa;
	position: absolute;
	top: 120rpx;
	left: 50rpx;
	z-index: 1;
}

.content-header {
	height: 70rpx;
}

.title {
	font-size: 33rpx;
	font-weight: bold;
	color: #3da7ff;
	line-height: 38px;
}

.footer {
	height: 150rpx;
	display: flex;
	align-items: center;
	justify-content: space-around;
}

.box-des-scroll {
	box-sizing: border-box;
	padding: 0 40rpx;
	height: 200rpx;
	text-align: left;
}

.box-des {
	font-size: 26rpx;
	color: #000000;
	line-height: 50rpx;
}

.progress-box {
	width: 100%;
}

.progress {
	width: 90%;
	height: 40rpx;
	border-radius: 35px;
}

.close-img {
	width: 70rpx;
	height: 70rpx;
	z-index: 1000;
	position: absolute;
	bottom: -120rpx;
	left: calc(50% - 70rpx / 2);
}

.content-button {
	text-align: center;
	flex: 1;
	font-size: 30rpx;
	font-weight: 400;
	color: #ffffff;
	border-radius: 40rpx;
	margin: 0 18rpx;

	height: 80rpx;
	line-height: 80rpx;

	background: linear-gradient(to right, #1785ff, #3da7ff);
}

.flex-column {
	display: flex;
	flex-direction: column;
	align-items: center;
}
</style>
